//! 工具模块
//! 
//! 提供配置管理、指标收集等工具功能

pub mod config;
pub mod metrics;

use crate::Result;

/// 初始化日志系统
pub fn init_logging() -> Result<()> {
    tracing_subscriber::fmt()
        .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
        .with_target(false)
        .with_thread_ids(true)
        .with_file(true)
        .with_line_number(true)
        .init();
    
    tracing::info!("日志系统初始化完成");
    Ok(())
}

/// 格式化字节大小
pub fn format_bytes(bytes: u64) -> String {
    const UNITS: &[&str] = &["B", "KB", "MB", "GB", "TB"];
    let mut size = bytes as f64;
    let mut unit_index = 0;
    
    while size >= 1024.0 && unit_index < UNITS.len() - 1 {
        size /= 1024.0;
        unit_index += 1;
    }
    
    if unit_index == 0 {
        format!("{} {}", bytes, UNITS[unit_index])
    } else {
        format!("{:.2} {}", size, UNITS[unit_index])
    }
}

/// 格式化持续时间
pub fn format_duration(duration: std::time::Duration) -> String {
    let total_seconds = duration.as_secs();
    let hours = total_seconds / 3600;
    let minutes = (total_seconds % 3600) / 60;
    let seconds = total_seconds % 60;
    let millis = duration.subsec_millis();
    
    if hours > 0 {
        format!("{}h {}m {}s", hours, minutes, seconds)
    } else if minutes > 0 {
        format!("{}m {}s", minutes, seconds)
    } else if seconds > 0 {
        format!("{}.{:03}s", seconds, millis)
    } else {
        format!("{}ms", millis)
    }
}

/// 生成唯一ID
pub fn generate_id() -> String {
    use std::sync::atomic::{AtomicU64, Ordering};
    static COUNTER: AtomicU64 = AtomicU64::new(1);
    
    let timestamp = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_millis();
    
    let counter = COUNTER.fetch_add(1, Ordering::SeqCst);
    
    format!("{:x}-{:x}", timestamp, counter)
}

/// 验证SQL标识符
pub fn validate_identifier(name: &str) -> bool {
    if name.is_empty() || name.len() > 63 {
        return false;
    }
    
    // 第一个字符必须是字母或下划线
    let first_char = name.chars().next().unwrap();
    if !first_char.is_ascii_alphabetic() && first_char != '_' {
        return false;
    }
    
    // 其他字符必须是字母、数字或下划线
    name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}

/// 转义SQL字符串
pub fn escape_sql_string(s: &str) -> String {
    s.replace('\'', "''")
}

/// 解析连接字符串
pub fn parse_connection_string(conn_str: &str) -> Result<std::collections::HashMap<String, String>> {
    let mut params = std::collections::HashMap::new();
    
    for part in conn_str.split_whitespace() {
        if let Some((key, value)) = part.split_once('=') {
            params.insert(key.to_string(), value.to_string());
        }
    }
    
    Ok(params)
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_format_bytes() {
        assert_eq!(format_bytes(0), "0 B");
        assert_eq!(format_bytes(1023), "1023 B");
        assert_eq!(format_bytes(1024), "1.00 KB");
        assert_eq!(format_bytes(1536), "1.50 KB");
        assert_eq!(format_bytes(1048576), "1.00 MB");
        assert_eq!(format_bytes(1073741824), "1.00 GB");
    }
    
    #[test]
    fn test_format_duration() {
        assert_eq!(format_duration(std::time::Duration::from_millis(500)), "500ms");
        assert_eq!(format_duration(std::time::Duration::from_secs(1)), "1.000s");
        assert_eq!(format_duration(std::time::Duration::from_secs(65)), "1m 5s");
        assert_eq!(format_duration(std::time::Duration::from_secs(3665)), "1h 1m 5s");
    }
    
    #[test]
    fn test_generate_id() {
        let id1 = generate_id();
        let id2 = generate_id();
        
        assert_ne!(id1, id2);
        assert!(id1.contains('-'));
        assert!(id2.contains('-'));
    }
    
    #[test]
    fn test_validate_identifier() {
        assert!(validate_identifier("valid_name"));
        assert!(validate_identifier("_underscore"));
        assert!(validate_identifier("name123"));
        assert!(validate_identifier("CamelCase"));
        
        assert!(!validate_identifier(""));
        assert!(!validate_identifier("123invalid"));
        assert!(!validate_identifier("invalid-name"));
        assert!(!validate_identifier("invalid name"));
        assert!(!validate_identifier(&"a".repeat(64))); // 太长
    }
    
    #[test]
    fn test_escape_sql_string() {
        assert_eq!(escape_sql_string("normal"), "normal");
        assert_eq!(escape_sql_string("O'Reilly"), "O''Reilly");
        assert_eq!(escape_sql_string("'quoted'"), "''quoted''");
    }
    
    #[test]
    fn test_parse_connection_string() {
        let conn_str = "host=localhost port=5432 dbname=test user=postgres";
        let params = parse_connection_string(conn_str).unwrap();
        
        assert_eq!(params.get("host"), Some(&"localhost".to_string()));
        assert_eq!(params.get("port"), Some(&"5432".to_string()));
        assert_eq!(params.get("dbname"), Some(&"test".to_string()));
        assert_eq!(params.get("user"), Some(&"postgres".to_string()));
    }
}
